package com.esdk.sql;

import com.esdk.esdk;
import com.esdk.sql.orm.AbstractSelect;

/**
 * 联表策略枚举，用于定义关联条件
 * @see JoinSelect
 */
public enum JoinStrategy {

  /*字段相同，先找id再找code*/
  SAME_NAME((joinSelect, joinType, leftSelect, rightSelect) -> {
    String[] leftSelectNames = leftSelect.getNames();
    String[] rightSelectNames = rightSelect.getNames();
    String[] options = {"id", "code"};
    String[] exclude = {"valid", "tenant_id"};
    String[] overlap = esdk.array.overlap(leftSelectNames, rightSelectNames);
    if(overlap.length == 0)
      throw new SQLRuntimeException("%s和%s没有相同的字段".formatted(leftSelect.getTable().getTableName(), rightSelect.getTable().getTableName()));
    String finalName = overlap[0];
    findOptionName:for (String filedName : overlap) {
      if(esdk.array.contains(exclude, filedName)) continue;
      for (String option : options) {
        if(filedName.toLowerCase().endsWith(option)){
          finalName = filedName;
          break findOptionName;
        }
      }
    }
    joinSelect.join(joinType, rightSelect, new Field(leftSelect.getTable(), finalName), new Field(rightSelect.getTable(), finalName));
  }),

  /*[左表].id = [右表].[左表]_id*/
  LEFT_ID((joinSelect, joinType, leftSelect, rightSelect) -> {
    String[] leftSelectNames = leftSelect.getNames();
    String[] rightSelectNames = rightSelect.getNames();
    if(!esdk.array.contains(leftSelectNames, "id"))
      throw new SQLRuntimeException("%s没有id字段".formatted(leftSelect.getTable().getTableName()));
    String rightSelectAssocFiled = leftSelect.getTable().getTableName().concat("_id");
    if(!esdk.array.contains(rightSelectNames, rightSelectAssocFiled))
      throw new SQLRuntimeException("%s没有%s字段".formatted(rightSelect.getTable().getTableName(), rightSelectAssocFiled));
    joinSelect.join(joinType, rightSelect, new Field(leftSelect.getTable(), "id"), new Field(rightSelect.getTable(), rightSelectAssocFiled));
  }),

  /*[右表].id = [左表].[右表]_id*/
  RIGHT_ID((joinSelect, joinType, leftSelect, rightSelect) -> {
    String[] leftSelectNames = leftSelect.getNames();
    String[] rightSelectNames = rightSelect.getNames();
    if(!esdk.array.contains(rightSelectNames, "id"))
      throw new SQLRuntimeException("%s没有id字段".formatted(rightSelect.getTable().getTableName()));
    String leftSelectAssocFiled = rightSelect.getTable().getTableName().concat("_id");
    if(!esdk.array.contains(leftSelectNames, leftSelectAssocFiled))
      throw new SQLRuntimeException("%s没有%s字段".formatted(leftSelect.getTable().getTableName(), leftSelectAssocFiled));
    joinSelect.join(joinType, rightSelect, new Field(leftSelect.getTable(), leftSelectAssocFiled), new Field(rightSelect.getTable(), "id"));
  }),



  ;

  private final StrategyFunc strategyFunc;

  JoinStrategy(StrategyFunc strategyFunc) {
    this.strategyFunc = strategyFunc;
  }

  interface StrategyFunc<S extends AbstractSelect>{
    void join(JoinSelect joinSelect, String joinType, S leftSelect, S rightSelect);
  }

  StrategyFunc getStrategyFunc() {
    return strategyFunc;
  }
}
